/*
 * Copyright 2011-2012 by The Regents of the University of California Licensed
 * under the Apache License, Version 2.0 (the "License"); you may not use this
 * file except in compliance with the License. you may obtain a copy of the
 * License from
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package edu.ucsd.db.bassarisk.schema;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import edu.ucsd.db.bassarisk.exception.SchemaValidationException;
import edu.ucsd.db.bassarisk.schema.Schema.SequenceRelationship;

public class DataSeqNestingOrder {
  private final Map<String, DataSequenceClass> initializedRunClasses;
  private final Map<String, Map<String, SequenceRelationship>> orderMap;

  public DataSeqNestingOrder() {
    this.orderMap = new HashMap<String, Map<String, SequenceRelationship>>();
    this.initializedRunClasses = new HashMap<String, DataSequenceClass>();
  }

  public void addName(final Schema schema, final String seqClassName)
      throws SchemaValidationException {
    DataSequenceClass seqClass = DataSequenceClass.findClass(schema, seqClassName);
    seqClass.initailize(schema);
    this.initializedRunClasses.put(seqClassName, seqClass);
    this.orderMap.put(seqClassName, new HashMap<String, SequenceRelationship>());
    Set<String> existingNames = this.orderMap.keySet();
    for (String existingName : existingNames) {
      DataSequenceClass existingClass = this.initializedRunClasses.get(existingName);
      SequenceRelationship relationship = seqClass.relationshipWith(existingClass);
      this.setRelationship(seqClassName, existingName, relationship);
    }
  }

  public boolean contains(final String name) {
    return this.orderMap.containsKey(name);
  }

  public SequenceRelationship getRelationship(final String runClassA,
                                              final String runClassB) {
    if (!this.orderMap.containsKey(runClassA)) { return null; }
    if (!this.orderMap.containsKey(runClassB)) { return null; }
    return this.orderMap.get(runClassA).get(runClassB);
  }

  private void setRelationship(final String runClassA, final String runClassB,
                               final SequenceRelationship relationship) {
    if (!this.orderMap.containsKey(runClassA)) {
      this.orderMap.put(runClassA, new HashMap<String, SequenceRelationship>());
    }
    if (!this.orderMap.containsKey(runClassB)) {
      this.orderMap.put(runClassB, new HashMap<String, SequenceRelationship>());
    }
    this.orderMap.get(runClassA).put(runClassB, relationship);
    this.orderMap.get(runClassB).put(runClassA,
                                     Schema.invertRelationship(relationship));
  }
}
